#include "framebuffer.h"
#include <QColor>
#include <QMutexLocker>
#include <QPainter>

FrameBuffer::FrameBuffer(int width, int height)
    : width(width)
    , height(height)
    , hasUpdates(false)
{
    image = QImage(width, height, QImage::Format_RGB32);
    image.fill(Qt::black);
}

FrameBuffer::~FrameBuffer()
{
}

void FrameBuffer::resize(int width, int height)
{
    QMutexLocker locker(&mutex);
    
    if (this->width != width || this->height != height) {
        this->width = width;
        this->height = height;
        image = QImage(width, height, QImage::Format_RGB32);
        image.fill(Qt::black);
        updatedRegions.clear();
        hasUpdates = true;
    }
}

void FrameBuffer::fill(const QColor &color)
{
    QMutexLocker locker(&mutex);
    image.fill(color);
    updatedRegions.append(image.rect());
    hasUpdates = true;
}

void FrameBuffer::updateRegion(const QImage &image, const QRect &region)
{
    QMutexLocker locker(&mutex);
    
    if (region.x() + region.width() <= this->image.width() && 
        region.y() + region.height() <= this->image.height()) {
        QPainter painter(&this->image);
        painter.drawImage(region, image);
        updatedRegions.append(region);
        hasUpdates = true;
    }
}

void FrameBuffer::updateRegions(const QList<QImage> &images, const QList<QRect> &regions)
{
    QMutexLocker locker(&mutex);
    
    if (images.size() != regions.size()) {
        return;
    }
    
    QPainter painter(&this->image);
    for (int i = 0; i < images.size(); ++i) {
        const QRect &region = regions[i];
        if (region.x() + region.width() <= this->image.width() && 
            region.y() + region.height() <= this->image.height()) {
            painter.drawImage(region, images[i]);
            updatedRegions.append(region);
        }
    }
    
    if (!images.isEmpty()) {
        hasUpdates = true;
    }
}

const QImage& FrameBuffer::getImage() const
{
    QMutexLocker locker(&mutex);
    return image;
}

QImage FrameBuffer::getImage(const QRect &region) const
{
    QMutexLocker locker(&mutex);
    return image.copy(region);
}

QList<QRect> FrameBuffer::getUpdatedRegions()
{
    QMutexLocker locker(&mutex);
    return updatedRegions;
}

void FrameBuffer::clearUpdatedRegions()
{
    QMutexLocker locker(&mutex);
    updatedRegions.clear();
    hasUpdates = false;
}

int FrameBuffer::getWidth() const
{
    return width;
}

int FrameBuffer::getHeight() const
{
    return height;
}

QSize FrameBuffer::getSize() const
{
    return QSize(width, height);
}

bool FrameBuffer::isEmpty() const
{
    QMutexLocker locker(&mutex);
    return !hasUpdates;
}